package com.example.capsule.service;

import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class SmsService {
    private static final Logger logger = LoggerFactory.getLogger(SmsService.class);

    private final Client smsClient;
    private final RedisService redisService;

    // 测试模式配置
    @Value("${sms.test-mode.enabled:true}")
    private boolean testModeEnabled;

    @Value("${sms.test-mode.code:123456}")
    private String testCode;

    @Value("${sms.test-mode.whitelist:}")
    private List<String> testWhitelist;

    @Value("${sms.aliyun.sign-name:时光胶囊}")
    private String signName;

    @Value("${sms.aliyun.template-code:SMS_000000}")
    private String templateCode;

    public SmsService(Client smsClient, RedisService redisService) {
        this.smsClient = smsClient;
        this.redisService = redisService;
        logger.info("短信服务初始化完成，测试模式: {}", testModeEnabled);
        logger.info("测试验证码: {}, 白名单: {}", testCode, testWhitelist);
    }

    /**
     * 发送验证码短信（支持测试模式）
     */
    public boolean sendVerificationCode(String phone) {
        try {
            logger.info("开始发送验证码到手机号: {}", phone);

            // 验证手机号格式
            if (!isValidPhone(phone)) {
                logger.warn("手机号格式不正确: {}", phone);
                throw new IllegalArgumentException("手机号格式不正确");
            }

            // 测试模式处理
            if (testModeEnabled) {
                return handleTestMode(phone);
            }

            // 检查发送频率限制
            String rateLimitKey = "sms:rate:" + phone;
            if (redisService.hasKey(rateLimitKey)) {
                logger.warn("手机号 {} 发送过于频繁", phone);
                throw new RuntimeException("发送过于频繁，请60秒后再试");
            }

            // 生成6位验证码
            String code = generateVerificationCode();
            logger.info("生成验证码: {} 给手机号: {}", code, phone);

            // 存储验证码到Redis，5分钟有效期
            String codeKey = "sms:code:" + phone;
            redisService.set(codeKey, code, 5, TimeUnit.MINUTES);

            // 设置发送频率限制
            redisService.set(rateLimitKey, "1", 60, TimeUnit.SECONDS);

            // 构建短信请求
            SendSmsRequest request = new SendSmsRequest()
                    .setPhoneNumbers(phone)
                    .setSignName(signName)
                    .setTemplateCode(templateCode)
                    .setTemplateParam("{\"code\":\"" + code + "\"}");

            logger.debug("发送短信请求: {}", Common.toJSONString(request));

            // 发送短信
            RuntimeOptions runtime = new RuntimeOptions();
            SendSmsResponse response = smsClient.sendSmsWithOptions(request, runtime);

            // 记录响应
            logger.info("短信发送响应: {}", Common.toJSONString(response.getBody()));

            boolean success = "OK".equals(response.getBody().getCode());
            if (success) {
                logger.info("短信发送成功到手机号: {}", phone);
            } else {
                logger.error("短信发送失败到手机号: {}, 错误: {}", phone, response.getBody().getMessage());
            }

            return success;

        } catch (Exception e) {
            logger.error("短信发送失败到手机号: {}", phone, e);

            // 测试模式下即使出错也返回成功
            if (testModeEnabled) {
                logger.warn("测试模式下忽略发送错误");
                return true;
            }

            throw new RuntimeException("短信发送失败: " + e.getMessage(), e);
        }
    }

    /**
     * 测试模式处理
     */
    private boolean handleTestMode(String phone) {
        // 检查白名单
        if (!testWhitelist.isEmpty() && !testWhitelist.contains(phone)) {
            logger.warn("测试模式：手机号 {} 不在白名单中", phone);
            return false;
        }

        String code;
        if ("123456".equals(testCode) || "000000".equals(testCode)) {
            // 使用固定测试码
            code = testCode;
        } else {
            // 生成随机验证码
            code = generateVerificationCode();
        }

        logger.info("测试模式: 验证码 {} 已生成", code);

        // 输出到控制台
        System.out.println("=== 测试模式短信验证码 ===");
        System.out.println("手机号: " + phone);
        System.out.println("验证码: " + code);
        System.out.println("======================");

        // 存储验证码
        try {
            String codeKey = "sms:code:" + phone;
            redisService.set(codeKey, code, 5, TimeUnit.MINUTES);
        } catch (Exception e) {
            logger.warn("Redis存储失败，但测试模式下继续: {}", e.getMessage());
        }

        return true;
    }

    /**
     * 验证验证码（支持测试模式）
     */
    public boolean verifyCode(String phone, String code) {
        try {
            // 测试模式特殊处理
            if (testModeEnabled) {
                return handleTestVerify(phone, code);
            }

            String storedCode = (String) redisService.get("sms:code:" + phone);

            if (code == null || storedCode == null) {
                logger.warn("验证码验证失败: 手机号 {} 验证码为空或未发送", phone);
                return false;
            }

            boolean isValid = code.equals(storedCode);
            if (isValid) {
                logger.info("验证码验证成功: 手机号 {}", phone);
                // 验证成功后删除验证码
                redisService.delete("sms:code:" + phone);
            } else {
                logger.warn("验证码验证失败: 手机号 {} 输入: {}, 期望: {}", phone, code, storedCode);
            }

            return isValid;

        } catch (Exception e) {
            logger.error("验证码验证过程出错: 手机号 {}", phone, e);

            // 测试模式下允许特定验证码
            if (testModeEnabled) {
                return handleTestVerify(phone, code);
            }

            throw new RuntimeException("验证码验证失败", e);
        }
    }

    /**
     * 测试模式验证处理
     */
    private boolean handleTestVerify(String phone, String code) {
        // 1. 先尝试从Redis获取
        try {
            String storedCode = (String) redisService.get("sms:code:" + phone);
            if (storedCode != null && storedCode.equals(code)) {
                redisService.delete("sms:code:" + phone);
                return true;
            }
        } catch (Exception e) {
            logger.warn("Redis获取失败，使用测试逻辑");
        }

        // 2. 允许特定测试验证码
        boolean isValid = "123456".equals(code) || "000000".equals(code);

        if (isValid) {
            logger.info("测试模式验证成功: 手机号 {} 使用测试码 {}", phone, code);
        } else {
            logger.warn("测试模式验证失败: 手机号 {} 输入: {}", phone, code);
        }

        return isValid;
    }

    /**
     * 生成6位数字验证码
     */
    private String generateVerificationCode() {
        Random random = new Random();
        return String.format("%06d", random.nextInt(999999));
    }

    /**
     * 验证手机号格式
     */
    public boolean isValidPhone(String phone) {
        boolean valid = phone != null && phone.matches("^1[3-9]\\d{9}$");
        logger.debug("手机号 {} 格式验证: {}", phone, valid ? "有效" : "无效");
       return valid;
    }

    /**
     * 检查是否可以发送验证码（测试模式优化）
     */
    public boolean canSendCode(String phone) {
        try {
            // 测试模式跳过频率限制
            if (testModeEnabled) {
                return true;
            }

            return !redisService.hasKey("sms:rate:" + phone);
        } catch (Exception e) {
            logger.warn("Redis检查失败，测试模式下允许发送");
            return testModeEnabled;
        }
    }

    /**
     * 获取剩余验证时间
     */
    public long getRemainingTime(String phone) {
        try {
            return redisService.getExpire("sms:code:" + phone);
        } catch (Exception e) {
            logger.warn("获取剩余时间失败，返回默认值");
            return 300; // 5分钟
        }
    }

    /**
     * 获取下次可发送时间
     */
    public long getNextSendTime(String phone) {
        try {
            return redisService.getExpire("sms:rate:" + phone);
        } catch (Exception e) {
            logger.warn("获取下次发送时间失败，返回0");
            return 0;
        }
    }

    /**
     * 检查是否测试模式
     */
    public boolean isTestModeEnabled() {
        return testModeEnabled;
    }

    /**
     * 获取测试验证码
     */
    public String getTestCode() {
        return testCode;
    }

    // 在 SmsService.java 中添加以下方法：

    /**
     * 发送自定义短信（非验证码）
     * TODO: 需要实现具体的短信发送逻辑
     */
    public boolean sendCustomSms(String phone, String message) {
        try {
            logger.info("发送自定义短信到: {}, 内容: {}", phone, message);

            // 验证手机号格式
            if (!isValidPhone(phone)) {
                logger.warn("手机号格式不正确: {}", phone);
                return false;
            }

            // 测试模式处理
            if (testModeEnabled) {
                return handleTestCustomSms(phone, message);
            }

            // 检查发送频率限制
            String rateLimitKey = "sms:custom:rate:" + phone;
            if (redisService.hasKey(rateLimitKey)) {
                logger.warn("手机号 {} 发送自定义短信过于频繁", phone);
                return false;
            }

            // 设置发送频率限制（比验证码宽松）
            redisService.set(rateLimitKey, "1", 30, TimeUnit.SECONDS);

            // TODO: 实现具体的自定义短信发送逻辑
            // 这里需要调用短信服务商的自定义短信接口
            // 示例：
            // SendSmsRequest request = new SendSmsRequest()
            //         .setPhoneNumbers(phone)
            //         .setSignName(signName)
            //         .setTemplateCode("SMS_CUSTOM_TEMPLATE") // 需要专门的模板
            //         .setTemplateParam("{\"message\":\"" + message + "\"}");
            //
            // SendSmsResponse response = smsClient.sendSmsWithOptions(request, new RuntimeOptions());
            // return "OK".equals(response.getBody().getCode());

            // 暂时用控制台输出模拟
            System.out.println("=== 自定义短信 ===");
            System.out.println("收件人: " + phone);
            System.out.println("内容: " + message);
            System.out.println("================");

            return true;

        } catch (Exception e) {
            logger.error("发送自定义短信失败: {}", phone, e);

            // 测试模式下即使出错也返回成功
            if (testModeEnabled) {
                return true;
            }

            return false;
        }
    }

    /**
     * 测试模式自定义短信处理
     */
    private boolean handleTestCustomSms(String phone, String message) {
        // 检查白名单
        if (!testWhitelist.isEmpty() && !testWhitelist.contains(phone)) {
            logger.warn("测试模式：手机号 {} 不在白名单中", phone);
            return false;
        }

        // 输出到控制台
        System.out.println("=== 测试模式自定义短信 ===");
        System.out.println("收件人: " + phone);
        System.out.println("内容: " + message);
        System.out.println("======================");

        return true;
    }
}